May 2018

WebMaps in R with Leaflet

Introduction

Outline

Basic Maps

  • Marker Maps
  • Adding Popups

Data Maps

  • Symbology for mapping point data
  • Choropleth maps
  • Adding Legends

Doing More

  • Customizing the UI
  • Sharing your maps

Setup

This workshop/tutorial will walk you through the basics of using the Leaflet mapping package in R. You can follow along in any of the three formats:

  • Tutorial Page (leaflet-webmaps-in-R-sp2018.html)
  • Raw code (leaflet-webmaps-in-R-sp2018.R)
  • Slides (leaflet-webmaps-in-R-sp2018-slides.html)

Make sure you can copy and paste from one of the above into the script.

To begin, lets set up our packages and environment.

Loading packages

Load the packages we will use today

library(leaflet)
library(RColorBrewer)
library(sp)
library(rgdal)
library(htmlwidgets)
library(magrittr) # or dplyr

Install any packages that you do not have on your computer

# install.packages("leaflet")
# install.packages("RColorBrewer")
# install.packages("sp")
# install.packages("rgdal")
# install.packages("htmlwidgets")
# install.packages("magrittr") # or dplyr

Set working directory

to the folder in which you unzipped the workshop files

Leaflet

Leaflet

Leaflet is a lightweight, yet powerful javascript library for creating interactive web maps.

Leaflet maps are a combination of HTML and Javascript code that is meant to be rendered in a web browser.

We can use the R leaflet package to create Leaflet maps in R

Our First Leaflet Map

Our first Leaflet map

map1 <- leaflet()       # Initialize the map object
map1 <- addTiles(map1)  # Add basemap tiles
map1                    # Display the map

Our first Leaflet map

map1 <- leaflet()       # Initialize the map object
map1 <- addTiles(map1)  # Add basemap tiles - default is OpenStreetMap
map1                    # Display the map

Setting the view

We specify the center and zoom level for the map

map1 <- leaflet() %>%
        addTiles() %>%  
        setView(lat=37.870044, lng=-122.258169, zoom = 15)
map1  

Setting the view

map1  # setView(lat=37.870044, lng=-122.258169, zoom = 15)

Piping Syntax

Requires dplyr or magrittr package to be loaded

map2 <- leaflet() %>%
        addTiles() %>%  
        setView(lat=37.870044, lng=-122.258169, zoom = 15)
map2   

Piping gives us the same map

map2

Syntax Comparison

Regular

map1 <- leaflet()        
map1 <- addTiles(map1)   
map1 <- setView(map1, lat=37.870044, lng=-122.258169, zoom = 15)
map1                  

Piping

map2 <- leaflet() %>%
        addTiles() %>%  
        setView(lat=37.870044, lng=-122.258169, zoom = 15)
map2   

WARNING: Don't name your map object map

Challenge

Rerun the piping code changing the zoom level

  • What zoom level reveals the campus building that the map is centered on?
  • What zoom level shows all of berkeley?
  • What is the max/min zoom level that returns a basemap?

The basemap

By Default, Leaflet uses the OpenStreetMap basemap, which is added with the addTiles() function

leaflet() %>% addTiles() %>% 
           setView(lat=37.870, lng=-122.258, zoom = 15)

addProviderTiles

Use addProviderTiles with the name of the basemap to add a different basemap.

Below, we are using the ESRI World Street Map basemap.

map2 <- leaflet() %>%
        addProviderTiles("Esri.WorldStreetMap") %>% 
        setView(lat=37.870044, lng=-122.258169, zoom = 12)

View it

map2   #Using ESRI WorldStreetMap basemap

Specify a Basemap

CartoDB Positron Basemap

leaflet() %>% addProviderTiles("CartoDB.Positron") %>% 
    setView(lat=37.870044, lng=-122.258169, zoom = 12)

Add A Custom Map Image

Berkeley, 1880

Here we are combining addTiles and addProviderTiles

mapurl <- "https://mapwarper.net/maps/tile/25477/{z}/{x}/{y}.png"

map2 <- leaflet() %>%
  addProviderTiles("CartoDB.Positron") %>%
  addTiles(mapurl) %>%  # custom map image
  setView(lat=37.870044, lng=-122.258169, zoom = 13)

Berkeley, 1880

map2  # Map of Berkeley, 1880 overlaid on the CartoDB basemap

Questions?

Mapping Data

Add Data with a Marker

Use addMarkers to add one or more data points to the map.

The map will automatically center on the data and determine an appropriate zoom level - if you don't use setView (commented out below).

You can override this by using setView.

map3 <- leaflet() %>%
  addTiles() %>%  # Add default OpenStreetMap map tiles
  #setView(lat=37.870044, lng=-122.258169, zoom = 17) %>%
  addMarkers(lat=37.870044, lng=-122.258169, popup="Go Bears!")

Add Data with a Marker

map3  # Display the map  - Click on the marker

Mapping Data Sets

The Sample Data

San Francisco Open Data Portal

SF Property Tax Rolls

This data set includes the Office of the Assessor-Recorder’s secured property tax roll spanning from 2015.

We are using this as a proxy for home values.

We are working with a simplified sample of the full data set.

Load the CSV file into a data frame

Set your working directory first to the folder where you downloaded the workshop files!

sfhomes <- read.csv('data/sfhomes15.csv', stringsAsFactors = FALSE)  
str(sfhomes)
## 'data.frame':    680 obs. of  11 variables:
##  $ SalesDate   : chr  "2015-08-21" "2015-08-13" "2015-12-29" "2015-07-06" ...
##  $ Address     : chr  "0000 2760 19TH                AV0015" "0000 0560AMISSOURI            ST0000" "0000 0718 LONG BRIDGE         ST1202" "0000 0899 VALENCIA            ST0202" ...
##  $ YrBuilt     : int  1979 2003 2016 2015 1961 1900 2015 NA 1947 1907 ...
##  $ NumBeds     : int  2 2 2 3 3 2 2 0 0 3 ...
##  $ NumBaths    : int  2 2 2 3 3 2 2 0 0 3 ...
##  $ NumUnits    : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ AreaSqFt    : int  1595 1191 1346 1266 1840 1256 1520 536 950 1837 ...
##  $ Neighborhood: chr  "Twin Peaks" "Potrero Hill" "Mission Bay" "Mission" ...
##  $ Value       : int  865000 1402560 2260993 1700000 2309692 2700564 1925000 583768 944180 1750001 ...
##  $ lat         : num  37.7 37.8 37.8 37.8 37.8 ...
##  $ lon         : num  -122 -122 -122 -122 -122 ...

Explore the data

head(sfhomes)
##    SalesDate                              Address YrBuilt NumBeds NumBaths
## 1 2015-08-21 0000 2760 19TH                AV0015    1979       2        2
## 2 2015-08-13 0000 0560AMISSOURI            ST0000    2003       2        2
## 3 2015-12-29 0000 0718 LONG BRIDGE         ST1202    2016       2        2
## 4 2015-07-06 0000 0899 VALENCIA            ST0202    2015       3        3
## 5 2015-06-12 0000 1333 JONES               ST0808    1961       3        3
## 6 2015-04-14 0000 1904 BAKER               ST0000    1900       2        2
##   NumUnits AreaSqFt    Neighborhood   Value      lat       lon
## 1        1     1595      Twin Peaks  865000 37.73601 -122.4741
## 2        1     1191    Potrero Hill 1402560 37.75920 -122.3965
## 3        1     1346     Mission Bay 2260993 37.77181 -122.3942
## 4        1     1266         Mission 1700000 37.75876 -122.4210
## 5        1     1840        Nob Hill 2309692 37.79362 -122.4149
## 6        1     1256 Pacific Heights 2700564 37.78881 -122.4437

Map the data

map4 <- leaflet() %>%
  addTiles() %>%   
  addMarkers(lat=sfhomes$lat, lng=sfhomes$lon, 
            popup= paste("Address:", sfhomes$Address,
                         "<br>", # add line break
                         "Property Value: ", sfhomes$Value))

Map the data

map4    # How did we map the data frame?

Popups Made Easier

We can save the popup code and re-use it instead of typing it over and over again.

popup_content <- paste("<b>Address:</b>", sfhomes$Address,"<br>", 
                       "<b>Property Value</b>: ", sfhomes$Value, "<br>",
                       "<b>Neighborhood:</b> ", sfhomes$Neighborhood, "<br>",
                       "<b>Num Bedrooms: </b>", sfhomes$NumBeds, "<br>",
                       "<b>Num Bathrooms:</b>", sfhomes$NumBaths
                       )



map4 <- leaflet() %>%
          addTiles() %>%   
          addMarkers(lat=sfhomes$lat, lng=sfhomes$lon, 
                     popup= popup_content)

Customizing the Popup

leaflet() %>%  addTiles() %>%   
      addMarkers(lat=sfhomes$lat, lng=sfhomes$lon, popup= popup_content)

Shorter syntax

Instead of this:

leaflet() %>%  
  addTiles() %>%   
  addMarkers(lat=sfhomes$lat, lng=sfhomes$lon, popup= popup_content)

We can use this syntax:

leaflet(sfhomes) %>%
  addTiles() %>%   
  addMarkers(~lon, ~lat, popup = popup_content)

Shorter Syntax

By passing in the name of the data object (sfhomes) to leaflet we can reference column names directly.

Below we are using the tilde (~) operator to map the data to the addMarkers function.

When the addMarkers function arguments lng= and lat= are not named they must be in the expected order (lng, lat).

leaflet(sfhomes) %>%
  addTiles() %>%   
  addMarkers(~lon, ~lat, popup = popup_content)

Dig deeper

The map is too crowded with Markers.

Read the addMarker documentation for options to address this.

addMarkers(map, lng = NULL, lat = NULL, layerId = NULL, 
           group = NULL, icon = NULL, popup = NULL, 
           options = markerOptions(), 
           clusterOptions = NULL, clusterId = NULL, 
           data = getMapData(map))

Cluster Option

map4 <- leaflet(sfhomes) %>%
  addTiles() %>%   
  addMarkers(~lon, ~lat, popup= popup_content,
            clusterOptions = 1)

Cluster Option

map4  # Explore the Map - hover over a cluster marker, zoom in.

Mapping Points as Circles

addCircleMarker

map4 <- leaflet(sfhomes) %>%
  addTiles() %>%   
  addCircleMarkers(~lon, ~lat, popup = popup_content)

Mapping Points as Circles

addCircleMarker

map4 

addCircleMarkers

addCircleMarkers(map, lng = NULL, lat = NULL, radius = 10, 
    layerId = NULL, group = NULL, stroke = TRUE, color = "#03F", 
    weight = 5, opacity = 0.5, 
    fill = TRUE, fillColor = color, ....)

Customize the circleMarkers

Change color, radius and stroke weight of circle markers

map4 <- leaflet(sfhomes) %>%
  addTiles() %>%   
  addCircleMarkers(~lon, ~lat, popup = popup_content,
             color="white", radius=6, weight=2,   # stroke
             fillColor="red",fillOpacity = 0.75   # fill
             )

Customize the circleMarkers

map4 

Data Driven Symbology

Cartography

Art + Science

Finding the right symbology - size, color, shape, etc

and mapping it to your data

Often requires a classification scheme

Mapping Points by Size

We can symbolize the size of points by data values by making the radius of the circle a function of a data value.

map4 <- leaflet(sfhomes) %>%
  addProviderTiles("CartoDB.Positron") %>%
  addCircleMarkers(~lon, ~lat, popup=popup_content,
             fillColor= NA, color="Red", weight=1, fillOpacity = 0,
             radius= ~NumBeds+2
             )

Mapping Points by Size

map4  # Size is a function of what variable?

addCircles vs addCircleMarkers

Circles and CircleMarkers look quite similar.

Circle radii are specified in meters while CircleMarkers are specified in pixels.

map4b <- leaflet(sfhomes) %>%
  addProviderTiles("CartoDB.Positron") %>%
  addCircles(~lon, ~lat, popup=popup_content,
             fillColor= NA, color="Red", 
             weight=1, fillOpacity = 0,
             radius= ~NumBeds*10
             )

map4b  # Compare map4 and map4b at different zoom levels

Mapping Data by Color

RColorBrewer

The RColorBrewer package is widely used to create color palettes for maps.

  • A color palette is a set of colors

There are 3 different types of color palettes

  1. Qualitative Color Palettes
  2. Sequential Color Palettes
  3. Diverging Color Palettes

Qualitative Palettes

Contrasting colors for categorical data

display.brewer.all(type="qual") 

display.brewer.pal(7, "Set3" )  # Try a different number of colors

Sequential Palettes

For highlighting trends in numerical data

display.brewer.all(type="seq")

Diverging Palettes

For highlighting the outliers

display.brewer.all(type="div")

Color Mapping in Leaflet

Map Homes by Neighborhood

Let's map sfhomes by the values in the Neighborhood column.

First, check out the RColorBrewer qualitative color palettes

display.brewer.all(type="qual")

Associate Colors with Data

leaflet::colorfactor takes as input a color palette and a domain that contains the full range of possible values to be mapped.

colorFactor(palette, domain, levels = NULL, ordered = FALSE,
  na.color = "#808080", alpha = FALSE, reverse = FALSE)

colorfactor returns a function specific to that domain that can be used to output a set of color values.

# Create a qualitative color palette
myColors <- colorFactor("Paired", sfhomes$Neighborhood) 

colorFactor

myColors <- colorFactor("Paired", sfhomes$Neighborhood) 
the_color_values <- myColors(sfhomes$Neighborhood)
length(the_color_values)
## [1] 680
length(the_color_values) == length(sfhomes$Neighborhood)
## [1] TRUE
unique(the_color_values)
##  [1] "#B15928" "#C4AAD2" "#E83F26" "#F57166" "#FBAE63" "#F6905B" "#3EA433"
##  [8] "#BFA19E" "#EDD279" "#4F8EC1" "#9BD277" "#FF9939" "#A6CEE3" "#7E54A6"
## [15] "#79A6A3" "#C3A176"

Homes by Neighborhood

Using a color palette

map4 <- leaflet(sfhomes) %>%
  addProviderTiles("CartoDB.Positron") %>%
  addCircleMarkers(~lon, ~lat,  
             popup= popup_content,
             fillColor= ~myColors(Neighborhood),
             radius=6, color=NA, weight=2, fillOpacity = 1
             )

Homes by Neighborhood

map4  # what neighborhood has the most 2015 transactions?

Add a Legend

Add a Legend

map4 <- leaflet(sfhomes) %>%
  addProviderTiles("CartoDB.Positron") %>%
  addCircleMarkers(~lon, ~lat, popup=popup_content,
             fillColor= ~myColors(Neighborhood),
             radius=6, color=NA, weight=2,fillOpacity = 1
             ) %>%
      addLegend(title = "Neighborhood", pal =  myColors,
                values = ~Neighborhood, opacity = 1, 
                position="bottomleft")

Add a legend

map4 

Mapping Colors to Numeric Values

Let's map the homes by value.

First, check out the sequential color palettes

display.brewer.all(type="seq")

leaflet::colorNumeric

For simple linear scaling of colors to values use colorNumeric.

  • This is used to create a proportional color map
colorNumeric(palette, domain, na.color = "#808080", alpha = FALSE,
  reverse = FALSE)

Create the numeric color mapping function

numColors <- colorNumeric("Reds", sfhomes$Value)

Proportional Color Map

Apply the numColors color mapping function to create a proportional color map

map4 <- leaflet(sfhomes) %>%
  addProviderTiles("CartoDB.Positron") %>%
  addCircleMarkers(~lon, ~lat, popup=popup_content,
             fillColor= ~numColors(Value),
             radius=6, color="grey", weight=1, fillOpacity = 1
             ) %>%
      addLegend(title = "Property Values", pal =  numColors,
                values = ~Value, opacity = 1, 
                position="bottomleft")

map4  # proportional color map

Quantile Colors

You can use colorQuantile to create a color palette based on quantile binning of the data. This is used to create a graduated color map.

colorQuantile(palette, domain, n = 4,
  probs = seq(0, 1, length.out = n + 1),
  na.color = "#808080", alpha = FALSE, reverse = FALSE)

The default is 4 bins, but you can set n manually (3 to 7)

Note: The colorBin function can be used to create color palettes based on different classification methods for binning the data, eg equal interval, natural breaks etc.

Creating a Graduated Color Map

# Use colorQuantile to create a color function for the data
quantColors <- colorQuantile("Reds", sfhomes$Value, n=5)

# Use the color function in the leaflet map
map4b <- leaflet(sfhomes) %>%
  addProviderTiles("CartoDB.Positron") %>%
  addCircleMarkers(~lon, ~lat, popup=popup_content,
             fillColor= ~quantColors(Value),
             radius=6, color="grey", weight=1,fillOpacity = 1
             ) 

map4b  # Graduated color map

Add A Legend

map4b %>%  addLegend(title = "Value", pal =  quantColors,
                values = ~Value, opacity = 1, 
                position="bottomleft")

Customize the Legend

map5 <-map4b %>%   addLegend(pal = quantColors, values = ~Value,
                     title = "Property Value, 2015",
                     position="bottomleft",
                     opacity=1,
                     labFormat = function(type, cuts, p) {
                      n = length(cuts)
                      cuts = paste0("$", format(cuts[-n], big.mark=","), 
                              " - ", "$",format(cuts[-1], big.mark=","))
                      }
                   )

map5  # Graduated Color Map

Proportional & Graduated Color Maps

Data Order

What's happening here?

sfhomes_low2high <- sfhomes[order(sfhomes$Value, decreasing = FALSE),]

map5 <- leaflet(sfhomes_low2high) %>%
  addProviderTiles("CartoDB.Positron") %>%
  addCircleMarkers(~lon, ~lat, popup=popup_content,
             fillColor= ~quantColors(Value),
             radius=6, color="grey", weight=1,fillOpacity = 1
             ) 

Order matters!

map5  # points reordered from low to high value

Questions

Recap

Recap

Basic Maps

  • addMarkers - Simple Marker Maps
  • addCircleMarkers - Circle Marker Maps

Data Maps

  • addCircles Proportional symbol maps
  • colorFactor - Category Maps
  • colorNumeric - Proportional color maps
  • colorQuantile - Graduated color maps

Geographic data

We have been working with geographic data in data frames

The coordinates are longitude and latitude

Next up, more complex spatial objects

Spatial Data in R

Spatial Data in R

We can use the sp and rgdal packages to import, manipulate and map more complex spatial objects.

sp - R classes and methods for spatial data

rgdal - Functions for importing and transforming spatial data

Let's use these to import data in ESRI Shapefiles

Read in an ESRI Shapefile

Read in the data

sf_md_hhi <- readOGR(dsn="data",layer="sf_medhhincome_acs5y_16")
## OGR data source with driver: ESRI Shapefile 
## Source: "data", layer: "sf_medhhincome_acs5y_16"
## with 196 features
## It has 5 fields

Explore the spatial data object

summary(sf_md_hhi)
## Object of class SpatialPolygonsDataFrame
## Coordinates:
##          min        max
## x -123.01392 -122.32756
## y   37.69274   37.86334
## Is projected: FALSE 
## proj4string :
## [+proj=longlat +datum=NAD83 +no_defs +ellps=GRS80 +towgs84=0,0,0]
## Data attributes:
##          GEOID    
##  06075010100:  1  
##  06075010200:  1  
##  06075010300:  1  
##  06075010400:  1  
##  06075010500:  1  
##  06075010600:  1  
##  (Other)    :190  
##                                                  NAME           variable  
##  Census Tract 101, San Francisco County, California:  1   B19013_001:196  
##  Census Tract 102, San Francisco County, California:  1                   
##  Census Tract 103, San Francisco County, California:  1                   
##  Census Tract 104, San Francisco County, California:  1                   
##  Census Tract 105, San Francisco County, California:  1                   
##  Census Tract 106, San Francisco County, California:  1                   
##  (Other)                                           :190                   
##     estimate           moe       
##  Min.   : 11971   Min.   :  739  
##  1st Qu.: 65893   1st Qu.: 9744  
##  Median : 89668   Median :15343  
##  Mean   : 91151   Mean   :16211  
##  3rd Qu.:117922   3rd Qu.:20032  
##  Max.   :205865   Max.   :89454  
##  NA's   :2        NA's   :2

Map a SpatialPolygonsDataFrame

Leaflet understands sp objects!!!

Map sf_md_hhi with addPolygons

map6 <- leaflet() %>%
  addTiles() %>%
  addPolygons(data=sf_md_hhi)

Map a SpatialPolygonsDataFrame

map6 # using addPolygons to map sf_md_hhi

Customizing the symbology

?addPolygons

addPolygons(map, lng = NULL, lat = NULL, layerId = NULL, group = NULL,
            stroke = TRUE, color = "#03F", weight = 5, opacity = 0.5,
            fill = TRUE, fillColor = color, fillOpacity = 0.2, 
            dashArray = NULL, smoothFactor = 1, noClip = FALSE, 
            popup = NULL, popupOptions = NULL, label = NULL, 
            labelOptions = NULL, options = pathOptions(),
            highlightOptions = NULL, data = getMapData(map))

Customizing the symbology

map6 <- leaflet() %>%
  setView(lng=-122.448889, lat=37.764645, zoom=12) %>%
  addProviderTiles("CartoDB.Positron") %>%
  
  # Customize the symbology of the polygons
  addPolygons(data=sf_md_hhi, color="grey", weight=1,
              fillColor="Orange", fillOpacity = 0.25)

SF Census Tracts

map6  # color="grey", weight=1, fillColor="Orange", fillOpacity = 0.25

Choropleth Maps

Choropleth Maps

Color regions based on data values.

The data values are classified into bins.

  • Quantile classification is the default.

Each bin gets a unique color from a color palette.

Create a choropleth map

Median Household Income is in the estimate column

Recipe:

  1. Create a color function based on the values of estimate
  2. Map the polygons setting the color to values produced by the color function

Create the Color Palette Function

  • First, select the name of the color palette
#display.brewer.all(type="seq") 

Then create the color mapping function

##
quantColors <- colorQuantile("YlOrRd", sf_md_hhi$estimate, n=5)

Create the Choropleth map

A choropleth map is a graduated color map of polygon data.

map6 <- leaflet() %>%
  setView(lng=-122.448889, lat=37.764645, zoom=12) %>%
  addProviderTiles("CartoDB.Positron") %>%
  # 
  addPolygons(data=sf_md_hhi, 
              color="white", 
              weight=1, 
              opacity=0.5,
              fillColor=~quantColors(estimate), 
              fillOpacity = 0.65,
              popup = paste0("$",sf_md_hhi$estimate))

Census Tracts by Med HH Income

map6  # choropleth map of median household income by census tract

Add a legend

map6 <- map6 %>% addLegend(pal = quantColors, 
                   values = sf_md_hhi$estimate,
                   title = "Median HH Income",
                   position="bottomleft",
                   opacity=1,
                   labFormat = function(type, cuts, p) {
                     n = length(cuts)
                     cuts = paste0("$", format(cuts[-n], big.mark=","), 
                             " - ", "$",format(cuts[-1], big.mark=","))
                   }
)

Med HH Income Legend

map6

Map Overlays

You can add multiple data layers to a leaflet map.

Let's add the sfhomes to the map

cheap <- sfhomes[sfhomes$Value < 1000000,]

map7 <- leaflet() %>%
  setView(lng=-122.448889, lat=37.764645, zoom=12) %>%
  addProviderTiles("CartoDB.Positron") %>%
  
  # Median household income polygons
  addPolygons(data=sf_md_hhi, color="white", weight=1, opacity=0.5,
              fillColor=~quantColors(estimate), fillOpacity = 0.65,
              popup = paste0("$",sf_md_hhi$estimate)) %>%
  
  # sfhomes points
  addCircleMarkers(data=cheap, popup=paste0("$",cheap$Value),
              color="black",weight=1, radius=6, 
              fillColor="white", fillOpacity = 0.75)

Map Overlays

map7  # sfhomes and median household income

Getting Control

We can add a layer switcher control with addLayersControl().

This allows us to toggle on/off the display of a map layer.

First, we need to assign a group to each map layer

?addLayersControl

Assign Group & Add Layers Control

map8 <- leaflet() %>%
          setView(lng=-122.448889, lat=37.764645, zoom=12) %>%
          addProviderTiles("CartoDB.Positron") %>%
          addPolygons(data=sf_md_hhi, color="white", weight=1, opacity=0.5,
              fillColor=~quantColors(estimate), fillOpacity = 0.65,
              popup = paste0("$",sf_md_hhi$estimate),
              group="Median HH Income"
          ) %>%
          addCircleMarkers(data=cheap, popup=paste0("$",cheap$Value),
              color="black",weight=1, radius=6, 
              fillColor="white", fillOpacity = 0.75,
              group="Property Values"
          ) %>%
          addLayersControl(
            overlayGroups = c("Property Values","Median HH Income"),
            options = layersControlOptions(collapsed = FALSE)
        )

Map with Layer Controls

map8

Add Basemap(s) to Layer Control

map8 <- leaflet() %>%
          setView(lng=-122.448889, lat=37.764645, zoom=12) %>%
          addProviderTiles("CartoDB.Positron", group="Simple Basemap") %>%
          addProviderTiles("Esri.WorldStreetMap", group="Streets Basemap")  %>%
          addTiles("", group="No Basemap") %>%  
          #
          addPolygons(data=sf_md_hhi, color="white", weight=1, opacity=0.5,
              fillColor=~quantColors(estimate), fillOpacity = 0.65,
              popup = paste0("$",sf_md_hhi$estimate),
              group="Median HH Income"
          ) %>%
          addCircleMarkers(data=cheap, popup=paste0("$",cheap$Value),
              color="black",weight=1, radius=6, 
              fillColor="white", fillOpacity = 0.75,
              group="Property Values"
          ) %>%
          addLayersControl(
            baseGroups = c("Simple Basemap", "Streets Basemap", "No Basemap"),
            overlayGroups = c("Property Values","Median HH Income"),
            options = layersControlOptions(collapsed = FALSE)
        )

Layer Controls

map8

Questions?

Sharing

Sharing your web map

Interactive Maps in R - check

Web Maps can be shared if online.

Easy way to go is RPubs

RPubs

You can share you map online by publishing it to RPubs.

  • You need to have an RPubs account to make that work.
  1. Enter the code for your map in the console

  2. In the Viewer window, click on the Publish icon.

RPubs

Saving your map

Another way to share your map is to save it to a file. You can then email it, host it on your own web server or host it on github, etc.

#library(htmlwidgets)
saveWidget(map7, file="testmap.html")

Open your file to by double-clicking on it in the Mac Finder or Windows Explorer.

Questions?

Next Steps

Many R packages for Leaflet maps

tmap

  • great for exploratory data analysis of sp objects within R
  • much easier than leaflet for creating Leaflet maps as well as publication ready static map images.

mapview

  • This is a new package similar to tmap. I haven't checked it out but I keep seeing it so I think it is emerging.

Why leaflet

Thanks

To you!

and to Josh Pepper who did an earlier workshop on which these materials are loosely based.